package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import static com.sky.constant.AutoFillConstant.SET_CREATE_USER;
import static com.sky.constant.AutoFillConstant.SET_UPDATE_USER;

@Aspect//申明此类为切面类
@Component
@Slf4j
public class AutoFillAspect {
    /*
    * 切入点表达式，指定在哪些类上进行切面处理
    * execution(* com.sky.mapper.*.*(..))指定在哪个包下的哪些方法
    * @annotation(com.sky.annotation.AutoFill)指定哪些类上使用了此注解
    * */
    @Pointcut("execution(* com.sky.mapper.*.*(..))&&@annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut() {}

    /*
    * 前置通知，在方法执行前进行增强
    * */
    @Before("autoFillPointCut()")
    public void autoFillBefore(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        log.info("开始进行公共字段自动填充");
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //得到方法上的注解
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        //得到数据库操作类型INSERT或UPDATE
        OperationType operationType = annotation.value();
        //得到方法的参数
        Object[] args = joinPoint.getArgs();
        Object entity = args[0];
        if(operationType== OperationType.INSERT){
            //是insert则create_user和update_user都要进行填充
            autofill(entity,SET_CREATE_USER);
            autofill(entity,SET_UPDATE_USER);
        }else {
            //是update只需对update_user进行填充
            autofill(entity,SET_UPDATE_USER);
        }
    }

    private void autofill(Object entity, String methodName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //得到方法
        Method method = entity.getClass().
                getDeclaredMethod(methodName, Long.class);
        //调佣方法并进行传参
        method.invoke(entity, BaseContext.getCurrentId());
    }
}
